﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace NFit.WordML
{
    public class WordFileMapHierarchy
    {
        [XmlIgnore]
        public WordFileMapHierarchy Parent { get; private set; }
        
        [XmlAttribute]
        public string StyleName { get; set; }

        [XmlAttribute]
        public string StyleId { get; set; }

        public List<WordFileMapHierarchy> Childs { get; set;}

        public WordFileMapHierarchy()
        {
        }

        public WordFileMapHierarchy(string style)
        {
            StyleName = style;
        }

        public WordFileMapHierarchy(string style, string styleid)
        {
            StyleName = style;
            StyleId = styleid;
        }

        public WordFileMapHierarchy Add(string style)
        {
            var child = new WordFileMapHierarchy(style);
            Add(child);
            return child;
        }

        private void InitChilds()
        {
            if (Childs == null)
                Childs = new List<WordFileMapHierarchy>();
        }

        public WordFileMapHierarchy Add(WordFileMapHierarchy child)
        {
            InitChilds();
            child.Parent = this;
            Childs.Add(child);
            return child;
        }
        
        public bool IsSameOrChildOf(WordFileMapHierarchy elt)
        {
            return elt == this || elt == null || IsChildOf(elt);
        }

        public bool IsChildOf(WordFileMapHierarchy elt)
        {
            if (Childs != null)
            {
                foreach (var child in elt.Childs)
                {
                    if (child == this)
                        return true;

                    if (child.IsChildOf(elt))
                        return true;
                }
            }

            return false;
        }

        public bool IsChildOf(string styleid)
        {
            WordFileMapHierarchy cParent = Parent;
            while (cParent != null)
            {
                if (cParent.StyleId == styleid)
                    return true;
                cParent = cParent.Parent;
            }
            return false;
        }

        public bool IsSameOrParentOf(WordFileMapHierarchy elt)
        {            
            return elt == this || (elt != null && IsParentOf(elt.StyleId));
        }

        public bool IsParentOf(WordFileMapHierarchy elt)
        {
            return IsParentOf(elt.StyleId);
        }

        public bool IsParentOf(string styleid)
        {
            if (Childs != null)
            {
                foreach (var child in Childs)
                {
                    if (child.StyleId == styleid)
                        return true;

                    if (child.IsParentOf(styleid))
                        return true;
                }
            }
            return false;
        }

        public WordFileMapHierarchy GetChildStyle(string styleId)
        {
            WordFileMapHierarchy res = null;

            if (styleId == null)
                return null;
            
            if (StyleId == styleId)
                return this;

            if (Childs != null)
            {
                foreach (var child in Childs)
                {
                    if (child.StyleId == styleId)
                        return child;

                    res = child.GetChildStyle(styleId);
                }
            }
            return res;
        }

        public void Init()
        {
            if (Childs != null)
            {
                foreach (var elt in Childs)
                {
                    elt.Parent = this;
                    elt.Init();
                }
            }
        }

        public static WordFileMapHierarchy Default()
        {
            var root=  new WordFileMapHierarchy();
            root.Add("heading 1").Add("heading 2").Add("heading 3").Add("heading 4").Add("heading 5").Add("heading 6");
            return root;
        }
    }
}